﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.IO.Compression;
namespace blenderbatchrender
{
    public partial class Form1 : Form
    {
        
        public Form1()
        {
            InitializeComponent();
        }

        private void button_setpath_Click(object sender, EventArgs e)
        {
            op1.FileName = "blender.exe";
            op1.Filter = "应用程序|*.exe";
            if(op1.ShowDialog()==DialogResult.OK)
            {
                Renderproperty.blenderpath = op1.FileName;   
            }
        }

        private void button_test_Click(object sender, EventArgs e)
        {
            Renderproperty.FinishJob();
            
            
        }
       
        public void Runblender(object filenames)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            ArrayList filename = (ArrayList)filenames;
            foreach(string fn in filename)
            {
                p.StartInfo.FileName = Renderproperty.blenderpath;
                p.StartInfo.Arguments = fn.ToString() + " -b -a";
                if(Renderproperty.outputpath!="")
                {
                    string fnwithoutex = Path.GetFileNameWithoutExtension(fn);
                    string outputpath = "";
                    string[] str = fnwithoutex.Split('_');
                    if(str.Length!=0)
                    {
                       outputpath =  Renderproperty.outputpath + "\\" + str[0];
                    }
                    else
                    {
                        outputpath = Renderproperty.outputpath + "\\" + fnwithoutex;
                    }
                    if(!Directory.Exists(outputpath))
                    {
                        Directory.CreateDirectory(outputpath);
                    }
                    
                    p.StartInfo.Arguments = fn.ToString() + " -b -o "+outputpath+"\\ -a";
                }
                
                p.StartInfo.UseShellExecute = false;    //是否使用操作系统shell启动
                p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                p.StartInfo.CreateNoWindow = true;//不显示程序窗口
                
                p.Start();//启动程序
                callback.Invoke(new EventHandler(delegate
                {
                    callback.AppendText("start mission: "+fn);
                    callback.AppendText(Environment.NewLine);
                }));
                //向cmd窗口发送输入信息
                // p.StandardInput.WriteLine(filename+" -b");

                p.StandardInput.AutoFlush = true;
               // p.StandardInput.WriteLine("exit");
                //向标准输入写入要执行的命令。这里使用&是批处理命令的符号，表示前面一个命令不管是否执行成功都执行后面(exit)命令，如果不执行exit命令，后面调用ReadToEnd()方法会假死
                //同类的符号还有&&和||前者表示必须前一个命令执行成功才会执行后面的命令，后者表示必须前一个命令执行失败才会执行后面的命令



                //获取cmd窗口的输出信息
                string output = p.StandardOutput.ReadLine();

                StreamReader reader = p.StandardOutput;
                string line = reader.ReadLine();
                while (!reader.EndOfStream && Renderproperty.ifRunning)
                {
                    //str += line + "  ";
                    line = reader.ReadLine();
                    if(ifshowcallback.Checked)
                    {
                        callback.Invoke(new EventHandler(delegate
                        {
                            callback.AppendText(line);
                            callback.AppendText(Environment.NewLine);

                        }));
                    }

                }

                //p.WaitForExit();//等待程序执行完退出进程
                if(!Renderproperty.ifRunning) p.Kill();
                //while (Renderproperty.ifRunning)
                //{
                //    if (p.HasExited)
                //        break;
                //}
                p.Close();

                Renderproperty.finishCount++;
                if(Renderproperty.finishCount==Renderproperty.missonCount)
                {
                    Renderproperty.FinishJob();
                    Renderproperty.ifRunning = false;
                    bool b=false;
                    callback.Invoke(new EventHandler(delegate
                    {
                        callback.AppendText("Finish all jobs!!");
                        callback.AppendText(Environment.NewLine);
                    }));
                    if(ifupload.Checked)
                    {
                        zipdir(Renderproperty.outputpath);
                        b = upload(Renderproperty.outputpath + ".zip");


                    }
                    if(ifshutdown.Checked)
                    {
                        if (ifupload.Checked)
                        {
                            if(!b)
                            {
                                return;
                            }
                        }

                        p.StartInfo.FileName = "cmd.exe";
                        p.StartInfo.UseShellExecute = false;    //是否使用操作系统shell启动
                        p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                        p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                        p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                        p.StartInfo.CreateNoWindow = true;//不显示程序窗口
                        p.Start();
                        p.StandardInput.WriteLine("shutdown -s -t 0");
                    }
                }
            }
        }
        private void zipdir(string path)
        {         
            ZipFile.CreateFromDirectory(path, path + ".zip", CompressionLevel.Optimal, true);
            callback.Invoke(new EventHandler(delegate
            {
                callback.AppendText("压缩打包到:" + path + ".zip 文件中");
                callback.AppendText(Environment.NewLine);
            }));
       
        }
        private bool upload(string file)
        {
            FtpWeb fw = new FtpWeb("serverip", "/", "userid", "password");
            fw.GotoDirectory("/", true);
            bool b =  fw.Upload(file);
            callback.Invoke(new EventHandler(delegate
            {
                callback.AppendText("上传压缩包:" +file);
                callback.AppendText(Environment.NewLine);
            }));
            if (b)
            {
                return true;
            }
            else
                return false;
       
        }
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //初始化输出目录
            Renderproperty.outputpath = "";
            //初始化列表对象
            Renderproperty.gpulist=new System.Collections.ArrayList();
            Renderproperty.cpulist = new System.Collections.ArrayList();
            //检测blender的目录
            string s = Renderproperty.getBlenderPath().GetValue("").ToString();
            string[] ss = s.Split('\"');
            if(ss[1]!="")
            {
                Renderproperty.blenderpath = ss[1];
                callback.AppendText("检测到blender："+ss[1]);
                callback.AppendText(Environment.NewLine);
                
            }
            
             
        }

        private void callback_TextChanged(object sender, EventArgs e)
        {
            if(callback.Lines.Length>60000)
            {
                callback.Clear();
            }
            callback.Select(callback.TextLength, 0);
            callback.ScrollToCaret();
        }

        private void Gpulist_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.All;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void Gpulist_DragDrop(object sender, DragEventArgs e)
        {
            //string fname = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
            string[] fnames = ((string[])e.Data.GetData(DataFormats.FileDrop));
            foreach(string fname in fnames)
            {
                if (Path.GetExtension(fname) == ".blend")
                    this.Gpulist.Items.Add(fname);
            }
            
        }

        private void Gpulist_ValueMemberChanged(object sender, EventArgs e)
        {
            
        }

        private void cpulist_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.All;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void cpulist_DragDrop(object sender, DragEventArgs e)
        {
            string[] fnames = ((string[])e.Data.GetData(DataFormats.FileDrop));
            foreach (string fname in fnames)
            {
                if (Path.GetExtension(fname) == ".blend")
                    this.cpulist.Items.Add(fname);
            }
        }

        private void gpuclear_Click(object sender, EventArgs e)
        {
            Gpulist.Items.Clear();
        }

        private void gpudelete_Click(object sender, EventArgs e)
        {
            Gpulist.Items.RemoveAt(Gpulist.SelectedIndex);
        }

        private void cpuclear_Click(object sender, EventArgs e)
        {
            cpulist.Items.Clear();
        }

        private void cpudelete_Click(object sender, EventArgs e)
        {
            cpulist.Items.RemoveAt(cpulist.SelectedIndex);
        }

        private void infoclear_Click(object sender, EventArgs e)
        {
            callback.Clear();
        }

        private void gpuimport_Click(object sender, EventArgs e)
        {
            op1.Filter = "blender文件|*.blend";
            op1.Multiselect = true;
            if(op1.ShowDialog()==DialogResult.OK)
            {
                Gpulist.Items.Add(op1.FileName);
            }
        }

        private void cpuimport_Click(object sender, EventArgs e)
        {
            op1.Filter = "blender文件|*.blend";
            op1.Multiselect = true;
            if (op1.ShowDialog() == DialogResult.OK)
            {
                cpulist.Items.Add(op1.FileName);
            }
        }

        private void button_startrender_Click(object sender, EventArgs e)
        {
            
            callback.Clear();
            if (Gpulist.Items.Count > 0)
            {
                Renderproperty.gpulist.Clear();
                foreach (object item in Gpulist.Items)
                {
                    Renderproperty.gpulist.Add(item.ToString());
                }
                //ThreadPool.QueueUserWorkItem(Runblender, Renderproperty.gpulist);
                Thread t1 = new Thread(new ParameterizedThreadStart(Runblender));
                t1.Start(Renderproperty.gpulist);
                Renderproperty.ifRunning = true;
            }
            if (cpulist.Items.Count > 0)
            {
                Renderproperty.cpulist.Clear();
                foreach (object item in cpulist.Items)
                {
                    Renderproperty.cpulist.Add(item.ToString());
                }
                
                  //  ThreadPool.QueueUserWorkItem(Runblender, Renderproperty.cpulist);


                Thread t2 = new Thread(new ParameterizedThreadStart(Runblender));
                t2.Start(Renderproperty.cpulist);
                Renderproperty.ifRunning = true;
            }
            Renderproperty.missonCount = Gpulist.Items.Count + cpulist.Items.Count;

        }

        private void button1_Click(object sender, EventArgs e)
        {
            Renderproperty.ifRunning = false;
            KillProcessExists();
        }
        private void KillProcessExists()
        {
            Process[] ps = Process.GetProcesses();
            foreach (Process item in ps)
            {
                if (item.ProcessName == "blender")
                {
                    item.Kill();
                }
                if (item.ProcessName == "blender-app")
                {
                    item.Kill();
                }
            }
           
        }  
        private void button_output_Click(object sender, EventArgs e)
        {
            sp1.FileName = "o1.png";
            sp1.Filter = "图像文件|*.png";
            if(sp1.ShowDialog()==DialogResult.OK)
            {
                Renderproperty.outputpath = Path.GetDirectoryName(sp1.FileName);
                callback.AppendText("输出目录设置为：" + Path.GetDirectoryName(sp1.FileName));
                callback.AppendText(Environment.NewLine);
            }
        }

       

    }
}
